
package com.ys.chatserver.http.file.d;

import com.alibaba.fastjson.JSONObject;
import com.eva.epc.common.util.CommonUtils;
import com.eva.framework.httpfile.FileDownload;
import com.eva.framework.utils.LoggerFactory;
import com.ys.chatserver.http.file.u.ShortVideoUploader;
import com.ys.chatserver.http.logic.filter.JwtHelper;
import com.ys.chatserver.http.logic.filter.JwtParam;
import com.ys.chatserver.tool.EmptyUtils;
import com.ys.chatserver.tool.MD5Util;
import org.slf4j.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 短视频消息的视频首帧预览图片下载实现类。
 *
 * @author Jack Jiang
 * @since 4.4
 */
//FIXME: 在更苛刻的安全性要求下，可考虑要求客户端把token字段带上来，以便进行更强的合法身份检查
public class ShortVideoThumbDownloader extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {

    private static final Logger logger = LoggerFactory.getLog();
    /**
     * 默认短视频首帧预览图片
     */
    public final static String DEFAULT_THUMB_FILE_NAME = "default_short_video_thumb.jpg";

    /* (non-Java-doc)
     * @see javax.servlet.http.HttpServlet#HttpServlet()
     */
    public ShortVideoThumbDownloader() {
        super();
    }

    /**
     * Servlet规范中本protected方法由public void service(,,)方法调用, 而public void service(,,)
     * 则由Web容器调用(所以它是public公共方法),因此一般情况下尽量避免重写public void service(,,)方法
     * ,而重写父类的本protedted方法则比较合理.
     */
    protected void service(HttpServletRequest req, HttpServletResponse res)
            throws ServletException, IOException {
        LoggerFactory.getLog().debug("[HTTP][短视频首帧_DOWN]下载首帧预览图：你传过来的参数"
                + "video_file_md5=" + req.getParameter("video_file_md5")
                + ",thumb_image_file_name=" + req.getParameter("thumb_image_file_name")
                + ",default_thumb_if_no=" + req.getParameter("default_thumb_if_no")
                + ",[---- " + req.getContextPath() + "-" + req.getRequestURL() + "]");

        String video_file_md5 = req.getParameter("video_file_md5");
        String imageFileNameToCient = req.getParameter("thumb_image_file_name");

        // 【web端专用】：此参数为“1”时，表示当没有读取到短视频预览图时，会返回默认图片（
        // 这主要用于Web网页里显示时，否则因为没有图片数据返回而会在页面上显示一个“破图”img
        // 元素，那就难看死了！）
        String _defaultThumbIfNo = req.getParameter("default_thumb_if_no");
        boolean defaultThumbIfNo = (_defaultThumbIfNo != null && _defaultThumbIfNo.equals("1"));
        String queryString = req.getQueryString();
        String authToken;
        String time;
        String token = req.getParameter("token");
        if (Objects.isNull(token)) {
            token = req.getHeader("token");
            time = req.getHeader("time");
            authToken = req.getHeader("authToken");
        } else {
            time = req.getParameter("time");
            authToken = req.getParameter("authToken");
            queryString = queryString.substring(0, queryString.indexOf("&token"));
        }
        String path = String.format("/api/%s?%s", getServletName(), queryString);
        Map<String, String> map = new HashMap<>();
        map.put("token", token);
        map.put("time", time);
        map.put("path", path);
        String s = MD5Util.MD5_32(JSONObject.toJSONString(map));
        if (authToken == null) {
            logger.error("无权限访问");
            return;
        }
        if (!authToken.equals(s)) {
            logger.error("无权限访问");
            return;
        }
        if (EmptyUtils.isNotEmpty(token)) { //token校验
            JwtParam jwtParam = JwtHelper.parseJwt(token);
            String userUid = jwtParam.getUserId();
            try {
                if (JwtHelper.tokenAuth(jwtParam)) {
                    processBinaryDownload(res
                            , userUid
                            , ShortVideoUploader.getShortVideoFileSaveDir()
                            , imageFileNameToCient
                            , imageFileNameToCient
                            , defaultThumbIfNo);
                }
            } catch (Exception e) {
                logger.error("无权限访问");
            }
        } else {
            logger.error("无权限访问");
        }
    }

    /**
     * HTTP文件下载实现方法.
     * <p>
     * 本方法没有任何异常地返回即意味着成功处理完成.
     *
     * @param file_dir              要下载的文件所位于的服务器磁盘目录（此dir的结尾需要"/"哦）
     * @param fileNameForServerDisk 要下载的服务端磁盘文件名
     * @param fileNameToClient      返回给客户端的文件名（客户端可以用此文件名保存在它的本地，此文件名跟fileNameForServerDisk是不同的哦）
     * @param defaultThumbIfNo      【web端专用】：此参数为“1”时，表示当没有读取到短视频预览图时，会返回默认图片（
     *                              这主要用于Web网页里显示时，否则因为没有图片数据返回而会在页面上显示一个“破图”img元素，那就难看死了！）
     */
    private void processBinaryDownload(HttpServletResponse res
            , String userUid, String file_dir
            , String fileNameForServerDisk, String fileNameToClient
            , boolean defaultThumbIfNo) throws IOException {
        try {
            if (!CommonUtils.isStringEmpty(fileNameForServerDisk, true)
                    && !CommonUtils.isStringEmpty(fileNameToClient, true)) {
                LoggerFactory.getLog().debug("[HTTP]用户【" + userUid + "】要下载的视频首帧图片文件 " + fileNameForServerDisk
                        + "(" + fileNameToClient + ")将立即开始处理过程 ......");

                String filePath = file_dir + fileNameForServerDisk;
                File file = new File(filePath);

                // 当图片不存在时，是否需要使用默认图（使用默认图返回的情况，主要针对Web端）
                if (defaultThumbIfNo && !file.exists()) {
                    file = new File(ShortVideoThumbDownloader.class
                            .getResource(DEFAULT_THUMB_FILE_NAME).toURI());
                }

                // 实施文件下载
                FileDownload.download(res, file
                        , fileNameToClient, FileDownload.CONTENT_TYPE_JPEG, false);
            } else
                LoggerFactory.getLog().warn("[HTTP]对不起,用户【" + userUid + "】要下载的视频首帧图片(fileNameForServerDisk=" + fileNameForServerDisk + ")不存在！");
        } catch (Exception e) {
            LoggerFactory.getLog().warn("[HTTP]用户【" + userUid + "】的下载的视频首帧图片文件不存在，本次下次已提前结束(" + e.getMessage() + ")");
        }
    }
}
